"""
自定义出参处理示例
"""
from flask import jsonify, Response
from functools import wraps
from marshmallow import Schema, fields
import json
from datetime import datetime


def api_response(code=200, message="操作成功", data=None, status_code=200):
    """
    标准API响应格式
    """
    response = {
        "code": code,
        "message": message,
        "data": data
    }
    
    return jsonify(response), status_code


def success_response(data=None, message="操作成功", code=200):
    """成功响应"""
    return api_response(code=code, message=message, data=data)


def error_response(message="操作失败", code=400, data=None, status_code=400):
    """错误响应"""
    return api_response(code=code, message=message, data=data, status_code=status_code)


def serialize_response(schema_class=None, many=False):
    """
    装饰器：序列化响应数据
    """
    def decorator(f):
        @wraps(f)
        def decorated_function(*args, **kwargs):
            # 执行原始函数
            result = f(*args, **kwargs)
            
            # 如果已经是格式化的响应，直接返回
            if isinstance(result, tuple) and len(result) >= 2 and isinstance(result[0], dict) and 'code' in result[0]:
                return result
            
            # 如果有schema，使用schema序列化数据
            if schema_class:
                schema = schema_class(many=many)
                if isinstance(result, tuple):
                    # 如果返回的是(response, status_code)格式
                    response_data, status_code = result
                    serialized_data = schema.dump(response_data)
                    return success_response(data=serialized_data), status_code
                else:
                    serialized_data = schema.dump(result)
                    return success_response(data=serialized_data)
            
            # 没有schema，直接返回数据
            if isinstance(result, tuple):
                # 如果返回的是(response, status_code)格式
                response_data, status_code = result
                return success_response(data=response_data), status_code
            else:
                return success_response(data=result)
        
        return decorated_function
    return decorator


# 使用Marshmallow定义响应数据序列化模式
class UserSchema(Schema):
    """用户数据序列化模式"""
    id = fields.Int()
    email = fields.Email()
    username = fields.Str()
    is_admin = fields.Bool()
    is_active = fields.Bool()
    created_at = fields.DateTime(format='iso')
    updated_at = fields.DateTime(format='iso')


class PostSchema(Schema):
    """文章数据序列化模式"""
    id = fields.Int()
    title = fields.Str()
    content = fields.Str()
    created_at = fields.DateTime(format='iso')
    updated_at = fields.DateTime(format='iso')
    
    # 嵌套用户信息
    author = fields.Nested(UserSchema, only=['id', 'username'])
    
    # 自定义字段
    excerpt = fields.Method('get_excerpt')
    
    def get_excerpt(self, obj):
        """生成文章摘要"""
        if not obj.content:
            return ""
        return obj.content[:100] + "..." if len(obj.content) > 100 else obj.content


class PaginationSchema(Schema):
    """分页信息序列化模式"""
    page = fields.Int()
    per_page = fields.Int()
    total = fields.Int()
    pages = fields.Int()
    has_next = fields.Bool()
    has_prev = fields.Bool()


class UserListSchema(Schema):
    """用户列表响应模式"""
    users = fields.List(fields.Nested(UserSchema))
    pagination = fields.Nested(PaginationSchema)


# 使用示例
@serialize_response(schema_class=UserSchema)
def get_user(user_id):
    """获取单个用户示例"""
    # 在这里获取用户数据
    user = {
        "id": user_id,
        "email": "user@example.com",
        "username": "testuser",
        "is_admin": False,
        "is_active": True,
        "created_at": datetime.now(),
        "updated_at": datetime.now()
    }
    
    return user


@serialize_response(schema_class=UserListSchema)
def get_users_list():
    """获取用户列表示例"""
    # 在这里获取用户列表数据
    users = [
        {
            "id": 1,
            "email": "user1@example.com",
            "username": "user1",
            "is_admin": False,
            "is_active": True,
            "created_at": datetime.now(),
            "updated_at": datetime.now()
        },
        {
            "id": 2,
            "email": "user2@example.com",
            "username": "user2",
            "is_admin": True,
            "is_active": True,
            "created_at": datetime.now(),
            "updated_at": datetime.now()
        }
    ]
    
    pagination = {
        "page": 1,
        "per_page": 10,
        "total": 2,
        "pages": 1,
        "has_next": False,
        "has_prev": False
    }
    
    return {
        "users": users,
        "pagination": pagination
    }


def create_user():
    """创建用户示例 - 手动格式化响应"""
    # 在这里处理创建用户逻辑
    # ...
    
    new_user = {
        "id": 3,
        "email": "newuser@example.com",
        "username": "newuser",
        "is_admin": False,
        "is_active": True,
        "created_at": datetime.now(),
        "updated_at": datetime.now()
    }
    
    return success_response(
        data=new_user,
        message="用户创建成功",
        code=201
    ), 201


def handle_error():
    """错误处理示例"""
    try:
        # 模拟错误
        raise ValueError("这是一个示例错误")
    except ValueError as e:
        return error_response(
            message=str(e),
            code=400,
            data={"error_type": "ValueError"}
        )


# 自定义响应类
class APIResponse(Response):
    """自定义API响应类"""
    def __init__(self, data=None, code=200, message="操作成功", status=200, **kwargs):
        response_data = {
            "code": code,
            "message": message,
            "data": data
        }
        
        # 设置默认内容类型
        kwargs.setdefault('mimetype', 'application/json')
        
        # 将数据转换为JSON字符串
        response_json = json.dumps(response_data, ensure_ascii=False, default=str)
        
        super().__init__(response=response_json, status=status, **kwargs)


# 使用自定义响应类的示例
def custom_response_example():
    """使用自定义响应类的示例"""
    user_data = {
        "id": 1,
        "email": "user@example.com",
        "username": "testuser"
    }
    
    return APIResponse(
        data=user_data,
        code=200,
        message="获取用户成功",
        status=200
    )